package edu.gatech.cc.liam.geometry.linear;

import java.util.Map.Entry;

import edu.gatech.cc.liam.core.Globals;

public abstract class Vector implements Iterable<Entry<Integer, Double>> {
	public abstract double get(int i);
	public abstract void set(int i, double value);
	public abstract int dimensions();
	public abstract void scale(Double scaleFactor);
	public abstract Vector clone();
	public abstract boolean equals(Object arg0);
	public abstract int hashCode();
	public abstract boolean softEquals(Vector anotherPoint, double tolerance);
	public abstract double dotProduct(Vector v);
	public abstract int getNumEntries();
	
	public void add(Vector v) {
		assert v.dimensions() == this.dimensions();
		for(Entry<Integer, Double> e : v) {
			int i = e.getKey();
			double value = e.getValue();
			add(i, value); // this[i] += v[i];
		}
	}
	
	public void add(int index, double value) {
		set(index, get(index) + value);
	}
	
//	public double dotProduct(Vector v) {
//		assert v.dimensions() == this.dimensions();
//		double sum = 0;
//		for(Entry<Integer, Double> e : v) {
//			int i = e.getKey();
//			double value = e.getValue();
//			sum += this.get(i) * value;
//		}
//		return sum;
//	}
	
	public boolean isDistribution() {
		double sum = 0;
		for(Entry<Integer, Double> e : this) {
			Double value = e.getValue();
			if(value < -Globals.TOLERANCE || value > 1.0 + Globals.TOLERANCE)
				return false;
			sum += value;
		}
		return Math.abs(sum - 1.0) < Globals.TOLERANCE;
	}
	
	public boolean softEquals(Vector anotherPoint) {
		return softEquals(anotherPoint, Globals.TOLERANCE);
	}
	
}
